Skip to content

Warn at fit when X contains likely-text columns - #1159

Merged
vahidblm merged 5 commits into
mainfrom
warn-on-likely-text-columns
Aug 10, 2026
Merged

Warn at fit when X contains likely-text columns#1159
vahidblm merged 5 commits into
mainfrom
warn-on-likely-text-columns

Conversation

@vahidblm

@vahidblm vahidblm commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Issue

No GitHub issue. This was driven by repeated reports of users fitting on free-text columns, which leads to silently worse results.

Motivation

High-cardinality string columns that cannot be parsed as numbers are labelled FeatureModality.TEXT by modality detection, but nothing used this label: they were silently swept into the same OrdinalEncoder as real categoricals (which selects columns by dtype), turning near-unique text into near-unique integer codes, without any warnings.

fit() now emits a UserWarning naming the affected columns and pointing at the fixes: convert to a numeric dtype (numbers stored as strings), or use tabpfn-client if it's a genuine text, or pass the column in categorical_features_indices if it's a real high-cardinality category (in this case, there won't be warnings).

The check runs inside detect_feature_modalities (the single place the TEXT labels are produced, before clean_data rebuilds the schema). Detection logic itself is not changed (purely diagnostic).


Public API Changes

  • No Public API changes (new warning only; no signatures changed)

How Has This Been Tested?

  • Unit tests in tests/test_preprocessing/test_modality_detection.py: free text warns; low-cardinality strings and fully numeric strings do not warn; a numeric column with one stray "N/A" token warns; columns declared categorical (both plain string and category dtype) do not warn.
  • One parametrized estimator-level test (classifier and regressor) in tests/test_preprocessing/test_modality_detection.py: fit warns and names the column, predict stays quiet, and categorical_features_indices silences it.
  • stacklevel=6 so the warning points at the caller's fit() line (the @config_context(...) decorator on fit adds a contextlib wrapper frame, on top of the detect_feature_modalities frame); pinned by warning.filename asserts in the tests.

Checklist

  • The changes have been tested locally.
  • Documentation has been updated (if the public API or usage changes) [no update is need, as this is just a warning].
  • A changelog entry has been added (see changelog/README.md).
  • The code follows the project's style guidelines.
  • I have considered the impact of these changes on the public API.

High-cardinality string columns that cannot be parsed as numbers are
labelled TEXT by modality detection, but nothing consumed the label:
they were silently swept into the OrdinalEncoder alongside real
categoricals, turning near-unique text into integer noise. fit() now
emits a UserWarning naming the affected columns and pointing at the
fixes (numeric dtype, tabpfn-client for genuine text, or
categorical_features_indices to declare a real high-cardinality
category, which also silences the warning).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@CLAassistant

CLAassistant commented Aug 5, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Comment thread src/tabpfn/validation.py Outdated
The @config_context(...) instance decorating fit() wraps it via
ContextDecorator.__call__, whose wrapper is a real frame in
contextlib.py, so stacklevel=4 blamed contextlib instead of the
caller's fit() line. Bump to 5 and pin it with warning.filename
asserts in the interface tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@bejaeger bejaeger left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @vahidblm ! Looks mostly good to me, please see my 2 comments.

Comment thread changelog/1159.added.md Outdated
Comment thread src/tabpfn/validation.py Outdated
Comment thread src/tabpfn/classifier.py Outdated
Per review feedback, the likely-text warning now fires from inside
detect_feature_modalities instead of being called separately by each
estimator. This gives a single call site (the one place TEXT labels are
produced) and a single place to test, so the classifier/regressor tests
collapse into one parametrized test under the modality-detection suite.

warn_if_text_features moves from validation to modality_detection;
stacklevel goes 5 -> 6 for the extra detect_feature_modalities frame.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vahidblm
vahidblm force-pushed the warn-on-likely-text-columns branch from d87662a to 0dbad7e Compare August 7, 2026 13:57
@vahidblm
vahidblm requested a review from bejaeger August 7, 2026 14:15
Refactor import statements for cleaner code.
bejaeger
bejaeger previously approved these changes Aug 7, 2026

@bejaeger bejaeger left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the two changes!
Two more nits, but otherwise LGTM! approving already

Comment thread src/tabpfn/preprocessing/modality_detection.py Outdated
Comment thread src/tabpfn/preprocessing/modality_detection.py Outdated

@LeoGrin LeoGrin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@vahidblm
vahidblm added this pull request to the merge queue Aug 10, 2026
Merged via the queue into main with commit d2a1ca1 Aug 10, 2026
18 checks passed
@vahidblm
vahidblm deleted the warn-on-likely-text-columns branch August 10, 2026 20:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants